package com.collections.excercises;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import com.collections.CompactHashMap;

public class MemoryConsumtion {
	
	private static Random randomNumber = new Random();
	private static int MAX_SIZE = 1_000_000;
	private static long diffBeforeAllocate,diffAfterAllocate;
	
	public static void setDiffBeforeAllocate(long diffBeforeAllocate) {
		MemoryConsumtion.diffBeforeAllocate = diffBeforeAllocate;
	}

	public static void main(String[] args) {
		System.out.println("=========\nArray");
		diffBeforeAllocate = getMemoryInfo();
		int[] array = new int[MAX_SIZE];
		fillStructure(array,MAX_SIZE);
		handleAfterAllocate();
		
		System.gc();
		
		System.out.println("=========\nLinkedList\n");
		diffBeforeAllocate = getMemoryInfo();
		fillStructure(new LinkedList<Integer>(),MAX_SIZE);
		handleAfterAllocate();
		
		System.gc();
		
		System.out.println("=========\nArrayList\n");
		diffBeforeAllocate = getMemoryInfo();
		fillStructure( new ArrayList<Integer>(),MAX_SIZE);
		handleAfterAllocate();
		
		System.gc();
		
		System.out.println("=========\nHashMap\n");
		diffBeforeAllocate = getMemoryInfo();
		fillStructure( new HashMap<Integer,Integer>(),MAX_SIZE);
		handleAfterAllocate();
		
		System.gc();
		
		System.out.println("=========\nTreeMap\n");
		diffBeforeAllocate = getMemoryInfo();
		fillStructure( new TreeMap<Integer,Integer>(),MAX_SIZE);
		handleAfterAllocate();
		
	}

	public static void handleAfterAllocate() {
		diffAfterAllocate = getMemoryInfo();
		System.out.println("Array difference: "+ (diffAfterAllocate-diffBeforeAllocate)+"\n");
		System.out.println("Approximate size per element: "+ (diffAfterAllocate-diffBeforeAllocate)/MAX_SIZE+"\n");
	}
	
	public static long getMemoryInfo(){
		long dif = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
		System.out.println("Total: " +Runtime.getRuntime().totalMemory()+
				"\nFree: "+ Runtime.getRuntime().freeMemory()+
				"\nDifference: "+ dif+
				"\n");
		return dif;
	}
	
	private static void fillStructure(int[] array, final int SIZE) {
		
		for (int i = 0; i < SIZE; i++) {
			array[i] = randomNumber.nextInt();
		}
	}
	
	private static void fillStructure(List<Integer> list, final int SIZE) {
		
		for (int i = 0; i < SIZE; i++) {
			list.add( randomNumber.nextInt() );
		}
	}
	
	public static void fillStructure(Map<Integer,Integer> map, final int SIZE) {
		
		for (int i = 0; i < SIZE; i++) {
			map.put(new Integer(i), new Integer(i));
		}
	}
	
	public static void fillStructure(CompactHashMap map, final int SIZE) {
		
		for (int i = 0; i < SIZE; i++) {
			map.put(i, i);
		}
	}

}
